/*
 * Copyright (c) 2021 IAR Systems AB.
 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
        MODULE  ?cstartup

#include "pico.h"
#include "hardware/regs/m0plus.h"
#include "hardware/regs/addressmap.h"
#include "hardware/regs/sio.h"
#include "pico/binary_info/defs.h"

#ifdef NDEBUG
#ifndef COLLAPSE_IRQS
#define COLLAPSE_IRQS
#endif
#endif

        ;; Forward declaration of sections.
        SECTION CSTACK1:DATA:NOROOT(3)
        SECTION CSTACK:DATA:NOROOT(3)
        SECTION Region$$Table:DATA:NOROOT(3)
        SECTION .binary_info:DATA:NOROOT(2)

        SECTION .vectors:CODE:ROOT(8)
        PUBLIC  __vector_table
        PUBLIC  __vectors

        DATA
__vector_table
__vectors
        DCD     sfe(CSTACK)
        DCD     _reset_handler            ; Reset Handler
        DCD     isr_nmi                   ; NMI Handler
        DCD     isr_hardfault             ; Hard Fault Handler
        DCD     0                         ; MPU Fault Handler
        DCD     0                         ; Bus Fault Handler
        DCD     0                         ; Usage Fault Handler
        DCD     0                         ; Reserved
        DCD     0                         ; Reserved
        DCD     0                         ; Reserved
        DCD     0                         ; Reserved
        DCD     isr_svcall                ; SVCall Handler
        DCD     0                         ; Debug Monitor Handler
        DCD     0                         ; Reserved
        DCD     isr_pendsv                ; PendSV Handler
        DCD     isr_systick               ; SysTick Handler

         ; External Interrupts
        DCD     isr_irq0
        DCD     isr_irq1
        DCD     isr_irq2
        DCD     isr_irq3
        DCD     isr_irq4
        DCD     isr_irq5
        DCD     isr_irq6
        DCD     isr_irq7
        DCD     isr_irq8
        DCD     isr_irq9
        DCD     isr_irq10
        DCD     isr_irq11
        DCD     isr_irq12
        DCD     isr_irq13
        DCD     isr_irq14
        DCD     isr_irq15
        DCD     isr_irq16
        DCD     isr_irq17
        DCD     isr_irq18
        DCD     isr_irq19
        DCD     isr_irq20
        DCD     isr_irq21
        DCD     isr_irq22
        DCD     isr_irq23
        DCD     isr_irq24
        DCD     isr_irq25
        DCD     isr_irq26
        DCD     isr_irq27
        DCD     isr_irq28
        DCD     isr_irq29
        DCD     isr_irq30
        DCD     isr_irq31

// all default exception handlers do nothing, and we can check for them being set to our
// default values by seeing if they point to somewhere between __defaults_isrs_start and __default_isrs_end

        PUBLIC __default_isrs_start
__default_isrs_start:

        THUMB

decl_isr_bkpt MACRO  _name
        PUBWEAK _name
_name:
        bkpt #0
        ENDM

        decl_isr_bkpt isr_invalid
        decl_isr_bkpt isr_nmi
        decl_isr_bkpt isr_hardfault
        decl_isr_bkpt isr_svcall
        decl_isr_bkpt isr_pendsv
        decl_isr_bkpt isr_systick

       PUBLIC __default_isrs_end
__default_isrs_end:

decl_isr MACRO _name
        PUBWEAK _name

_name:
        ENDM

        decl_isr isr_irq0
        decl_isr isr_irq1
        decl_isr isr_irq2
        decl_isr isr_irq3
        decl_isr isr_irq4
        decl_isr isr_irq5
        decl_isr isr_irq6
        decl_isr isr_irq7
        decl_isr isr_irq8
        decl_isr isr_irq9
        decl_isr isr_irq10
        decl_isr isr_irq11
        decl_isr isr_irq12
        decl_isr isr_irq13
        decl_isr isr_irq14
        decl_isr isr_irq15
        decl_isr isr_irq16
        decl_isr isr_irq17
        decl_isr isr_irq18
        decl_isr isr_irq19
        decl_isr isr_irq20
        decl_isr isr_irq21
        decl_isr isr_irq22
        decl_isr isr_irq23
        decl_isr isr_irq24
        decl_isr isr_irq25
        decl_isr isr_irq26
        decl_isr isr_irq27
        decl_isr isr_irq28
        decl_isr isr_irq29
        decl_isr isr_irq30
        decl_isr isr_irq31

// All unhandled USER IRQs fall through to here
        PUBLIC __unhandled_user_irq
__unhandled_user_irq:
        bl __get_current_exception
        subs r0, #16
        PUBLIC unhandled_user_irq_num_in_r0
unhandled_user_irq_num_in_r0:
        bkpt #0

// ----------------------------------------------------------------------------

        SECTION .binary_info_header:CODE:ROOT(2)
        PUBLIC binary_info_header

        DATA
// Header must be in first 256 bytes of main image (i.e. excluding flash boot2).
// For flash builds we put it immediately after vector table; for NO_FLASH the
// vectors are at a +0x100 offset because the bootrom enters RAM images directly
// at their lowest address, so we put the header in the VTOR alignment hole.

#if !PICO_NO_BINARY_INFO
binary_info_header:
        DCD BINARY_INFO_MARKER_START
        DCD SFB(.binary_info)
        DCD SFE(.binary_info)
        DCD SFB(Region$$Table) // IAR specific implementation
        DCD BINARY_INFO_MARKER_END
#endif

// ----------------------------------------------------------------------------

        SECTION .reset:CODE:REORDER:NOROOT(2)
        EXTERN  __iar_program_start
        EXTERN  rom_func_lookup

_reset_handler:
        // Only core 0 should run the C runtime startup code; core 1 is normally
        // sleeping in the bootrom at this point but check to be sure
        ldr  r0, =(SIO_BASE + SIO_CPUID_OFFSET)
        ldr  r0, [r0]
        cmp  r0, #0
        bne  hold_non_core0_in_bootrom

        // Jump to IAR startup code, which will initialize needed data
        ldr  r0, =__iar_program_start
        bx   r0

hold_non_core0_in_bootrom:
        ldr  r0, = 'W' | ('V' << 8)
        bl   rom_func_lookup
        bx   r0

        SECTION .text:CODE:NOROOT(2)
        EXTERN runtime_init
        PUBLIC __iar_data_init_done

__iar_data_init_done:
        // Called by IAR startup code after data initialization
        push {lr}
        ldr  r0, =runtime_init
        blx  r0
        pop  {pc}

        SECTION .text:CODE:NOROOT(2)
        PUBLIC __get_current_exception

__get_current_exception:
        mrs  r0, ipsr
        uxtb r0, r0
        bx   lr

// Stack and Heap sizes with IAR are defined in the linker file
// This exists for compatibility with Pico SDK, and is taken into account
// only if stack/heap size in the linker file is set to 0

        SECTION .stack:DATA:NOROOT(3)
        DS PICO_STACK_SIZE

        SECTION .heap:DATA:NOROOT(2)
        DS PICO_HEAP_SIZE

        END
